//Artigo de Kang 2004
#ifndef IMPLICITJACOBI_H
#define IMPLICITJACOBI_H
#include "integrationMethod.h"


class ImplicitJacobi : public IntegrationMethod
{
    public:
        ImplicitJacobi();

        ImplicitJacobi(double, double, std::vector<State>, std::vector< std::vector<Particle *> > &, std::vector< std::vector<Spring *> > &, bool, int, double,  double,  double, Vector3D);

        ~ImplicitJacobi();

        void calculate(bool, unsigned int, double); //calculate the new state

        void setThreshold(double _t) {threshold = _t;};

        void setMaxIteration(int _max) {maxIteration = _max;};

    private:
        double threshold;

        int maxIteration;

        Matrix populateMatrixMass(const State&, unsigned int, unsigned int); //returns the mass matrix of a given particle

        Matrix *derivativeForcePosition(const State& _state, Spring*, const Vector3D&, const Vector3D&, const Vector3D&, const Vector3D&, unsigned int);//calculate the Jacobian relating the position

        std::vector<Matrix*> vectorOfJacobianPosition(const State&, const Vector3D&, const Vector3D&, unsigned int, unsigned int);//returns an array containing all the Jacobian matrices related to a given particle

        Matrix derivatedForcePositionItself(const std::vector<Matrix*>&, unsigned int, unsigned int); //calculates the Jacobian matrix with respect to the position of the particle itself

        Vector3D forceResultantParticle(const State&, const Vector3D&, const Vector3D&, const std::vector<Matrix*>&, unsigned int, unsigned int); //calculating the force f~

        //Matrix *derivativeForceVelocity(const State&, Spring *, unsigned int); //calculate the Jacobian relating the velocity
        Matrix *derivativeForceVelocity(const State&, Spring *, const Vector3D&, const Vector3D&, unsigned int); //calculate the Jacobian relating the velocity

        //std::vector<Matrix*> vectorOfJacobianVelocity(const State&, unsigned int, unsigned int); //returns an array containing all the Jacobian matrices related to a given particle
        std::vector<Matrix*> vectorOfJacobianVelocity(const State &, const Vector3D&, unsigned int, unsigned int); //returns an array containing all the Jacobian matrices related to a given particle

        Matrix derivativeForceVelocityItself(const std::vector<Matrix*>&, unsigned int, unsigned int); //calculates the Jacobian matrix with respect to the velocity of the particle itself

        void calculateImplicitJacobi(State*,  const Vector3D&, const Vector3D&, const Vector3D&, unsigned int); //calculate the new position and speed
};

#endif // IMPLICITJACOBI_H
